package bigdata.monitor.binlog.utils;

import bigdata.monitor.binlog.entity.MonitorRule;


public class UnifiedRuleEngine {

    public static boolean evaluate(String binlogJson, MonitorRule rule) {
        String expr;
        if ("CUSTOM".equals(rule.getRuleType())) {
            // 替换 data -> ?
            expr = rule.getTriggerCondition();
        } else {
            // 基础规则：生成“通过条件”，然后外层加 NOT → 变成“违规条件”
            expr = buildPassCondition(rule);
            expr = "NOT (" + expr + ")";
        }
        return SqliteJsonRuleEvaluator.evaluate(binlogJson, expr);
    }

    private static String buildPassCondition(MonitorRule rule) {
        String simple = rule.getSimpleCondition();
        if (simple == null || !simple.contains(":")) {
            throw new IllegalArgumentException("Invalid simple_condition for rule: " + rule.getRuleCode());
        }

        String[] parts = simple.split(":", 2);
        String field = parts[0].trim();
        String spec = parts[1].trim();
        String jsonPath = "$.after." + field; // 默认从 after 提取

        switch (rule.getRuleType()) {
            case "TYPE":
                return convertTypeCheck(jsonPath, spec);
            case "ENUM":
                return convertEnumCheck(jsonPath, spec);
            case "LENGTH":
                return convertLengthCheck(jsonPath, spec);
            default:
                throw new IllegalArgumentException("Unsupported rule_type: " + rule.getRuleType());
        }
    }

    private static String convertTypeCheck(String jsonPath, String typeSpec) {
        // 检查是否为宽松模式（以 ? 结尾）
        boolean isLenient = typeSpec.endsWith("?");
        String type = isLenient ? typeSpec.substring(0, typeSpec.length() - 1) : typeSpec;

        switch (type.toLowerCase()) {
            case "int":
            case "integer":
                if (isLenient) {
                    // 宽松整数：接受 JSON 数字 或 符合整数格式的字符串
                    return String.format("json_type(json_extract(data, '%s')) = 'integer'", jsonPath);
                } else {
                    // 严格整数：仅接受 JSON 数字
                    return String.format("json_type(data, '%s') = 'integer'", jsonPath);
                }

            case "double":
            case "float":
                if (isLenient) {
                    // 宽松小数：接受 JSON 数字 或 符合小数格式的字符串
                    return String.format("json_type(json_extract(data, '%s')) = 'real'", jsonPath);
                } else {
                    // 严格小数：仅接受 JSON 数字
                    return String.format("json_type(data, '%s') = 'real'", jsonPath);
                }

            case "string":
                if (isLenient) {
                    throw new IllegalArgumentException("String type does not support lenient mode");
                }
                // 字符串校验：仅接受 JSON 字符串
                return String.format("json_type(data, '%s') = 'text'", jsonPath);

            default:
                throw new IllegalArgumentException("Unsupported type: " + type);
        }
    }

    private static String convertEnumCheck(String jsonPath, String enumSpec) {
        String[] values = enumSpec.split(",");
        StringBuilder inClause = new StringBuilder("json_extract(data, '");
        inClause.append(jsonPath).append("') IN (");
        for (int i = 0; i < values.length; i++) {
            if (i > 0) inClause.append(", ");
            inClause.append("'").append(values[i].trim()).append("'");
        }
        inClause.append(")");
        return inClause.toString();
    }

    private static String convertLengthCheck(String jsonPath, String lengthSpec) {
        int length = Integer.parseInt(lengthSpec);
        return String.format(
                "length(json_extract(data, '%s')) = %d",
                jsonPath, length
        );
    }
}

